home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsprefix / fsprefixOps.c < prev   
C/C++ Source or Header  |  1992-12-18  |  66KB  |  2,170 lines

  1. /* 
  2.  * fsPrefix.c --
  3.  *
  4.  *    Implementation of the prefix table.  The prefix table is used
  5.  *    to determine the server for a file depending on the
  6.  *    first part of the file's name.  Operations on pathnames get
  7.  *    passed through Fsprefix_LookupOperation (and Fsprefix_TwoNameOperation) that
  8.  *    handles the iteration over the prefix table that is due to redirections
  9.  *    from servers as a pathname wanders from domain to domain.  There
  10.  *    is also set of low-level procedures for direct operations on the prefix
  11.  *    table itself; add, delete, initialize, etc.
  12.  *
  13.  *    TODO: Extract the recovery related junk.  The prefix table is used
  14.  *    as a convenient place to record recovery state and synchronize
  15.  *    opens with re-opens, but the recov module's user-state flags should be
  16.  *    used instead.
  17.  *
  18.  * Copyright 1987 Regents of the University of California
  19.  * All rights reserved.
  20.  * Permission to use, copy, modify, and distribute this
  21.  * software and its documentation for any purpose and without
  22.  * fee is hereby granted, provided that the above copyright
  23.  * notice appear in all copies.  The University of California
  24.  * makes no representations about the suitability of this
  25.  * software for any purpose.  It is provided "as is" without
  26.  * express or implied warranty.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsprefix/fsprefixOps.c,v 9.16 92/07/14 15:36:18 jhh Exp $ SPRITE (Berkeley)";
  31. #endif not lint
  32.  
  33.  
  34. #include <sprite.h>
  35. #include <fs.h>
  36. #include <fsprefix.h>
  37. #include <fsprefixInt.h>
  38. #include <fsNameOps.h>
  39. #include <fsutil.h>
  40. #include <fsStat.h>
  41. #include <fsio.h>
  42. #include <vm.h>
  43. #include <rpc.h>
  44. #include <proc.h>
  45. #include <dbg.h>
  46. #include <string.h>
  47.  
  48. static List_Links prefixListHeader;
  49. static List_Links *prefixList = &prefixListHeader;
  50.  
  51. static Sync_Lock prefixLock = Sync_LockInitStatic("Fs:prefixLock");
  52. #define LOCKPTR (&prefixLock)
  53.  
  54. /*
  55.  * Forward references.
  56.  */
  57. static char *NameOp _ARGS_((int lookupOperation));
  58. static Fsprefix *PrefixInsert _ARGS_((char *prefix, int serverID, 
  59.         Fs_HandleHeader *hdrPtr, int domainType, int flags));
  60. static void PrefixUpdate _ARGS_((Fsprefix *prefixPtr, int serverID, 
  61.         Fs_HandleHeader *hdrPtr, int domainType, int flags));
  62. static ReturnStatus LocatePrefix _ARGS_((char *fileName, int serverID, 
  63.         int *domainTypePtr, Fs_HandleHeader **hdrPtrPtr));
  64. static ReturnStatus GetPrefix _ARGS_((char *fileName, Boolean follow, 
  65.         Fs_HandleHeader **hdrPtrPtr, Fs_FileID *rootIDPtr,
  66.         char **lookupNamePtr, int *domainTypePtr,
  67.         Fsprefix **prefixPtrPtr));
  68. static void GetNilPrefixes _ARGS_((List_Links *listPtr));
  69. static ReturnStatus DumpExportList _ARGS_((Fsprefix *prefixPtr, int size, 
  70.         char *buffer));
  71.  
  72.  
  73.  
  74. /*
  75.  *----------------------------------------------------------------------
  76.  *
  77.  * Fsprefix_LookupOperation --
  78.  *
  79.  *    This uses the prefix table to choose a server and domain-type for
  80.  *    a pathname lookup operation.  This is called by the routines in
  81.  *    fsNameOps.c to do opens, removes, mkdir, rmdir, etc. etc.  The
  82.  *    domain-type name lookup routines may return pathnames instead of
  83.  *    results    if the pathname left the domain of the server originally
  84.  *    chosen by the prefix table.  This routine handles these "re-directed"
  85.  *    pathnames and hides the iteration between the prefix table and
  86.  *    the various servers.
  87.  *
  88.  * Results:
  89.  *    The results of the lookup operation.
  90.  *
  91.  * Side effects:
  92.  *    This may fault new entries into the prefix table.
  93.  *
  94.  *----------------------------------------------------------------------
  95.  */
  96. ReturnStatus
  97. Fsprefix_LookupOperation(fileName, operation, follow, argsPtr, resultsPtr, nameInfoPtr)
  98.     char     *fileName;    /* File name to lookup */
  99.     int     operation;    /* Operation to perform on the file */
  100.     Boolean    follow;        /* TRUE if lookup will follow links.  FALSE
  101.                  * means we won't indirect via a prefix which
  102.                  * matches the name exactly. */
  103.     Address     argsPtr;    /* Operation specific arguments.  NOTE: it
  104.                  * is assumed that the first thing in the
  105.                  * arguments is a prefix file ID, except on
  106.                  * the IMPORT/EXPORT operations.  We set the
  107.                  * prefix fileID here as a convenience to
  108.                  * the name lookup routines we branch to. */
  109.     Address     resultsPtr;    /* Operation specific results */
  110.     Fs_NameInfo    *nameInfoPtr;    /* If non-NIL, set up to contain state needed
  111.                  * to get back to the name server.  This is
  112.                  * used with FS_DOMAIN_OPEN which passes
  113.                  * in the nameInfoPtr from the stream. */
  114. {
  115.     ReturnStatus     status;        /* General error code */
  116.     int         domainType;    /* Set from the prefix table lookup */
  117.     Fs_HandleHeader     *hdrPtr;    /* Set from the prefix table lookup */
  118.     char         *lookupName;    /* Returned from the prefix table 
  119.                      * lookup */
  120.     Fs_RedirectInfo     *redirectInfoPtr;/* Returned from servers if their
  121.                      * lookup leaves their domain */
  122.     Fs_RedirectInfo     *oldInfoPtr;    /* Needed to free up the new name
  123.                      * buffer allocated by the domain
  124.                      * lookup routine. */
  125.     Fs_FileID        rootID;        /* ID of domain root */
  126.     Fsprefix         *prefixPtr;    /* Returned from prefix table lookup 
  127.                      * and saved in the file handle */
  128.     int         numRedirects = 0;/* Number of iterations between 
  129.                       * servers. This is used to catch the 
  130.                       * looping occurs with absolute links
  131.                       * that are circular. */
  132.  
  133.     redirectInfoPtr = (Fs_RedirectInfo *) NIL;
  134.     oldInfoPtr = (Fs_RedirectInfo *) NIL;
  135.  
  136.     if (sys_ShuttingDown) {
  137.     /*
  138.      * Lock processes out of the filesystem during a shutdown.
  139.      */
  140.     return(FAILURE);
  141.     }
  142.     do {
  143.     status = GetPrefix(fileName, follow, &hdrPtr, &rootID, &lookupName,
  144.                 &domainType, &prefixPtr);
  145.     if (status == SUCCESS) {
  146.         switch(operation) {
  147.         case FS_DOMAIN_IMPORT:
  148.         case FS_DOMAIN_EXPORT:
  149.             break;
  150.         case FS_DOMAIN_OPEN:
  151.         default: {
  152.             /*
  153.              * It is assumed that the first part of the bundled
  154.              * arguments are the prefix fileID, which indicates the
  155.              * start of the lookup, and the prefix rootID, which
  156.              * indicates the top of the domain.
  157.              */
  158.             register Fs_LookupArgs *lookupArgsPtr =
  159.                 (Fs_LookupArgs *)argsPtr;
  160.             lookupArgsPtr->prefixID = hdrPtr->fileID;
  161.             lookupArgsPtr->rootID = rootID;
  162.             break;
  163.         }
  164.         }
  165.         /*
  166.          * Fork out to the domain lookup operation.
  167.          */
  168.         status = (*fs_DomainLookup[domainType][operation])
  169.            (hdrPtr, lookupName, argsPtr, resultsPtr, &redirectInfoPtr);
  170.         switch (status) {
  171.             case FS_LOOKUP_REDIRECT: {
  172.             /*
  173.              * Lookup left the domain of the server chosen on the
  174.              * basis of the prefix table.  Generate an absolute name
  175.              * from the one returned by the server and loop back to
  176.              * the prefix table lookup.  We are careful to save a
  177.              * pointer to the redirect info because it contains the
  178.              * current pathname.  We also free any redirect info
  179.              * from previous iterations to prevent a core leak.
  180.              */
  181.             fs_Stats.prefix.redirects++; numRedirects++;
  182.             if (numRedirects > FS_MAX_LINKS) {
  183.             status = FS_NAME_LOOP;
  184.             fs_Stats.prefix.loops++;
  185.             } else {
  186.             status = FsprefixLookupRedirect(redirectInfoPtr, prefixPtr,
  187.                                   &fileName);
  188.             if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  189.                 free((Address)oldInfoPtr);
  190.             }
  191.             oldInfoPtr = redirectInfoPtr;
  192.             redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  193.             }
  194.             break;
  195.         }
  196.             case SUCCESS: {
  197.             if (nameInfoPtr != (Fs_NameInfo *)NIL) {
  198.             /*
  199.              * Set up the name info for the file.  The back pointer
  200.              * to the prefix table is used by us later to handle
  201.              * re-directs.  The rootID is noted here and passed
  202.              * to the server during relative lookups to trap
  203.              * ascending off the root of a domain via "..".
  204.              * The fileID is used by the attributes routines to get
  205.              * to the name server for open streams.
  206.              */
  207.             nameInfoPtr->fileID =
  208.                 ((Fs_OpenResults *)resultsPtr)->nameID;
  209.             nameInfoPtr->rootID = rootID;
  210.             nameInfoPtr->domainType = domainType;
  211.             nameInfoPtr->prefixPtr = prefixPtr;
  212.             }
  213.             break;
  214.         }
  215.         case RPC_TIMEOUT:
  216.         case RPC_SERVICE_DISABLED:
  217.         case FS_STALE_HANDLE: {
  218.             /*
  219.              * Block waiting for regular recovery of the prefix handle.
  220.              */
  221.             if (status == FS_STALE_HANDLE) {
  222.             fs_Stats.prefix.stale++;
  223.             } else {
  224.             fs_Stats.prefix.timeouts++;
  225.             }
  226.             Fsutil_WantRecovery(hdrPtr);
  227.             printf("%s of \"%s\" waiting for recovery\n",
  228.                 NameOp(operation), fileName);
  229.             status = Fsutil_WaitForRecovery(hdrPtr, status);
  230.             if (status == SUCCESS) {
  231.             /*
  232.              * Successfully waited for the server to reboot.
  233.              * Set the status to redirect so we go around the
  234.              * loop again.
  235.              */
  236.             status = FS_LOOKUP_REDIRECT;
  237.             } else if ((status != GEN_ABORTED_BY_SIGNAL) &&
  238.                        (fileName[0] == '/')) {
  239.             /*
  240.              * Recovery failed, so we clear handle of the prefix
  241.              * used to get to the server and try again in case
  242.              * the prefix is served elsewhere.
  243.              */
  244.             Fsprefix_HandleClose(prefixPtr, FSPREFIX_IMPORTED);
  245.             status = FS_LOOKUP_REDIRECT;
  246.             }
  247.             break;
  248.         }
  249.         default:
  250.             break;
  251.         }
  252.     }
  253.     } while (status == FS_LOOKUP_REDIRECT);
  254.     if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  255.     free((Address) oldInfoPtr);
  256.     }
  257.  
  258.     return(status);
  259. }
  260.  
  261. /*
  262.  *----------------------------------------------------------------------
  263.  *
  264.  * Fsprefix_TwoNameOperation --
  265.  *
  266.  *    This is a version of Fsprefix_LookupOperation that deals with two
  267.  *    pathnames.  The operation, either Rename or HardLink, will only
  268.  *    be attempted if the two pathnames are part of the same domain.
  269.  *    Two pathnames are determined to be in the same domain in part
  270.  *    by the domain specific lookup routine, and in part by us in
  271.  *    the following way.  The standard iteration over prefix table
  272.  *    for the first pathname (the already existing file) is done,
  273.  *    and the prefix info and relative name for it are passed to
  274.  *    the domain specific procedure along with our first guess as
  275.  *    to the domain and relative name of the second pathname.  The
  276.  *    domain specific procedure will abort with a CROSS_DOMAIN error
  277.  *    if it thinks the second pathname is served elsewhere.  In this case
  278.  *    this procedure has to verify that by getting the attributes of
  279.  *    the parent directory of the second name.  This may cause more
  280.  *    iteration over the prefix table to get the final prefix info
  281.  *    and relative name for the second name.  At that point we can
  282.  *    finally determine if the pathnames are in the same domain.
  283.  *
  284.  * Results:
  285.  *    The results of the two pathname operation.
  286.  *
  287.  * Side effects:
  288.  *    This may fault new entries into the prefix table.
  289.  *
  290.  *----------------------------------------------------------------------
  291.  */
  292. ReturnStatus
  293. Fsprefix_TwoNameOperation(operation, srcName, dstName, lookupArgsPtr)
  294.     int            operation;   /* FS_DOMAIN_RENAME, FS_DOMAIN_HARD_LINK */
  295.     char        *srcName;    /* Name of existing file */
  296.     char        *dstName;     /* New name, or link name */
  297.     Fs_LookupArgs    *lookupArgsPtr; /* ID information */
  298. {
  299.     ReturnStatus    status;        /* General error code */
  300.     int            srcDomain;    /* Domain type of srcName */
  301.     int         dstDomain;
  302.     Fs_HandleHeader    *srcHdrPtr;    /* Prefix handle of srcName */
  303.     Fs_HandleHeader     *dstHdrPtr;
  304.     char        *srcLookupName;    /* Relative version of srcName */
  305.     char         *dstLookupName;
  306.     Fsprefix        *srcPrefixPtr;    /* Prefix entry for srcName */
  307.     Fsprefix         *dstPrefixPtr;
  308.     Fs_FileID        srcRootID;    /* ID of srcName domain root */
  309.     Fs_FileID        dstRootID;
  310.     int            numRedirects;    /* To detect loops in directories */
  311.     Boolean        srcNameError;    /* TRUE if redirect info or stale
  312.                      * handle error applies to srcName,
  313.                      * FALSE if it applies to dstName. */
  314.     /*
  315.      * The domain-lookup routine allocates a buffer for a redirected pathname.
  316.      * FsprefixLookupRedirect() subsequently generates a new absolute pathname
  317.      * in this buffer.  We have to carefully hold onto this buffer during
  318.      * the next iteration of the lookup loop, and still be able to free
  319.      * it later to avoid core leaks.  The 'src' and 'dst' buffers are
  320.      * used for this reason.
  321.      */
  322.     Fs_RedirectInfo    *redirectInfoPtr = (Fs_RedirectInfo *) NIL;
  323.     Fs_RedirectInfo    *srcRedirectPtr = (Fs_RedirectInfo *) NIL;
  324.     Fs_RedirectInfo    *dstRedirectPtr = (Fs_RedirectInfo *) NIL;
  325.  
  326.     if (sys_ShuttingDown) {
  327.     /*
  328.      * Lock processes out of the filesystem during a shutdown.
  329.      */
  330.     return(FAILURE);
  331.     }
  332.     numRedirects = 0;
  333. getSrcPrefix:
  334.     status = GetPrefix(srcName, 0, &srcHdrPtr, &srcRootID, &srcLookupName,
  335.                     &srcDomain, &srcPrefixPtr);
  336.     if (status != SUCCESS) {
  337.     goto exit;
  338.     }
  339.     lookupArgsPtr->prefixID = srcHdrPtr->fileID;
  340.     lookupArgsPtr->rootID = srcRootID;
  341. getDstPrefix:
  342.     status = GetPrefix(dstName, 0, &dstHdrPtr, &dstRootID, &dstLookupName,
  343.                     &dstDomain, &dstPrefixPtr);
  344.     if (status != SUCCESS) {
  345.     goto exit;
  346.     }
  347. retry:
  348.     status = (*fs_DomainLookup[srcDomain][operation])
  349.        (srcHdrPtr, srcLookupName, dstHdrPtr, dstLookupName, lookupArgsPtr,
  350.             &redirectInfoPtr, &srcNameError);
  351.     switch(status) {
  352.     case RPC_SERVICE_DISABLED:
  353.     case RPC_TIMEOUT:
  354.         srcNameError = TRUE;
  355.         /*
  356.          * FALL THROUGH to regular recovery.
  357.          */
  358.     case FS_STALE_HANDLE: {
  359.         Fs_HandleHeader *staleHdrPtr;
  360.         staleHdrPtr = (srcNameError ? srcHdrPtr : dstHdrPtr);
  361.         Fsutil_WantRecovery(staleHdrPtr);
  362.         printf("%s of \"%s\" and \"%s\" waiting for recovery\n",
  363.                 NameOp(operation), srcName, dstName);
  364.         status = Fsutil_WaitForRecovery(staleHdrPtr, status);
  365.         if (status == SUCCESS) {
  366.         goto retry;
  367.         } else if (status != GEN_ABORTED_BY_SIGNAL) {
  368.         /*
  369.          * Recovery failed.  On absolute paths clear handle of the
  370.          * prefix used to get to the server and try again.
  371.          */
  372.         if ((srcNameError) && (srcName[0] == '/')) {
  373.             Fsprefix_HandleClose(srcPrefixPtr, FSPREFIX_IMPORTED);
  374.             status = FS_LOOKUP_REDIRECT;
  375.         } else if ((!srcNameError) && (dstName[0] == '/')) {
  376.             Fsprefix_HandleClose(dstPrefixPtr, FSPREFIX_IMPORTED);
  377.             status = FS_LOOKUP_REDIRECT;
  378.         }
  379.         }
  380.         break;
  381.     }
  382.     case FS_LOOKUP_REDIRECT:
  383.         /*
  384.          * The pathname left the server's domain, and it has returned
  385.          * us a new name.  We generate a new absolute pathname and
  386.          * save the pointer to the buffer.  It is now safe to free
  387.          * the buffer used during the last iteration as well.
  388.          */
  389.         fs_Stats.prefix.redirects++;
  390.         numRedirects++;
  391.         if (numRedirects > FS_MAX_LINKS) {
  392.         status = FS_NAME_LOOP;
  393.         fs_Stats.prefix.loops++;
  394.         } else if (srcNameError) {
  395.         status = FsprefixLookupRedirect(redirectInfoPtr, srcPrefixPtr,
  396.                       &srcName);
  397.         if (srcRedirectPtr != (Fs_RedirectInfo *)NIL) {
  398.             free((Address)srcRedirectPtr);
  399.         }
  400.         srcRedirectPtr = redirectInfoPtr;
  401.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  402.         } else {
  403.         status = FsprefixLookupRedirect(redirectInfoPtr, dstPrefixPtr,
  404.                       &dstName);
  405.         if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  406.             free((Address)dstRedirectPtr);
  407.         }
  408.         dstRedirectPtr = redirectInfoPtr;
  409.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  410.         }
  411.         break;
  412.     case FS_CROSS_DOMAIN_OPERATION: {
  413.         /*
  414.          * The server thinks the second name is not served by it.
  415.          * Here we attempt to get the attributes of the second name
  416.          * in order to bounce through links and end up with a good prefix.
  417.          */
  418.         ReturnStatus    status2;
  419.         Fs_OpenArgs        openArgs;
  420.         Fs_GetAttrResults    getAttrResults;
  421.         Fs_Attributes    dstAttr;    /* Attrs of destination */
  422.         Fs_FileID        dstFileID;
  423.  
  424.         openArgs.useFlags = FS_FOLLOW;
  425.         openArgs.permissions = 0;
  426.         openArgs.type = FS_FILE;
  427.         openArgs.clientID = rpc_SpriteID;
  428.         Fs_SetIDs((Proc_ControlBlock *)NIL, &openArgs.id);
  429.  
  430.         openArgs.prefixID = dstHdrPtr->fileID;
  431.         openArgs.rootID = dstRootID;
  432.  
  433.         getAttrResults.attrPtr = &dstAttr;
  434.         getAttrResults.fileIDPtr = &dstFileID;
  435. getAttr:
  436.         status2 = (*fs_DomainLookup[dstDomain][FS_DOMAIN_GET_ATTR])
  437.             (dstHdrPtr, dstLookupName, (Address)&openArgs,
  438.             (Address)&getAttrResults, &redirectInfoPtr);
  439.         switch(status2) {
  440.         default:
  441.             if (dstRootID.serverID != srcRootID.serverID ||
  442.             dstRootID.major != srcRootID.major) {
  443.             /*
  444.              * Really is a cross-domain operation.
  445.              */
  446.             status = FS_CROSS_DOMAIN_OPERATION;
  447.             break;
  448.             } else {
  449.             goto retry;
  450.             }
  451.         case FS_LOOKUP_REDIRECT: {
  452.             fs_Stats.prefix.redirects++;
  453.             numRedirects++;
  454.             if (numRedirects > FS_MAX_LINKS) {
  455.             status = FS_NAME_LOOP;
  456.             fs_Stats.prefix.loops++;
  457.             } else {
  458.             status = FsprefixLookupRedirect(redirectInfoPtr, dstPrefixPtr,
  459.                           &dstName);
  460.             if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  461.                 free((Address)dstRedirectPtr);
  462.             }
  463.             dstRedirectPtr = redirectInfoPtr;
  464.             redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  465.             srcNameError = FALSE;
  466.             /*
  467.              * Will fall out and then zip up to getDstPrefix.
  468.              */
  469.             }
  470.             break;
  471.         }
  472.         case RPC_SERVICE_DISABLED:
  473.         case RPC_TIMEOUT:
  474.         case FS_STALE_HANDLE: {
  475.             Fsutil_WantRecovery(dstHdrPtr);
  476.             printf("Get Attr of \"%s\" waiting for recovery\n",
  477.                      dstName);
  478.             status2 = Fsutil_WaitForRecovery(dstHdrPtr, status2);
  479.             if (status2 == SUCCESS) {
  480.             goto getAttr;
  481.             } else if ((status != GEN_ABORTED_BY_SIGNAL) &&
  482.                        (dstName[0] == '/')) {
  483.             Fsprefix_HandleClose(dstPrefixPtr, FSPREFIX_IMPORTED);
  484.             status = FS_LOOKUP_REDIRECT;
  485.             srcNameError = FALSE;
  486.             }
  487.             break;
  488.         }
  489.         }
  490.         break;
  491.     }
  492.     default:
  493.         /*
  494.          * SUCCESS or simple lookup failure.
  495.          */
  496.         break;
  497.     }
  498.     if (status == FS_LOOKUP_REDIRECT) {
  499.     if (srcNameError) {
  500.         goto getSrcPrefix;
  501.     } else {
  502.         goto getDstPrefix;
  503.     }
  504.     }
  505. exit:
  506.     if (srcRedirectPtr != (Fs_RedirectInfo *)NIL) {
  507.     free((Address)srcRedirectPtr);
  508.     }
  509.     if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  510.     free((Address)dstRedirectPtr);
  511.     }
  512.     return(status);
  513. }
  514.  
  515. /*
  516.  *----------------------------------------------------------------------
  517.  *
  518.  * FsprefixLookupRedirect --
  519.  *
  520.  *    Process a filename returned from a server after the lookup left
  521.  *    the server's domain.  This takes any prefix information and adds
  522.  *    to new entries to the prefix table, then it recomputes a new filename
  523.  *    and returns that so the caller can re-iterate the lookup.
  524.  *
  525.  * Results:
  526.  *    A return status, and a new file name.
  527.  *
  528.  * Side effects:
  529.  *    If the server tells us about a prefix it gets added to the
  530.  *    prefix table, but with no token or domain type.
  531.  *
  532.  *----------------------------------------------------------------------
  533.  */
  534. ReturnStatus
  535. FsprefixLookupRedirect(redirectInfoPtr, prefixPtr, fileNamePtr)
  536.     Fs_RedirectInfo    *redirectInfoPtr;/* New name and prefix from server */
  537.     Fsprefix        *prefixPtr;    /* Prefix table entry used to select
  538.                      * the server. */
  539.     char **fileNamePtr;            /* Return, new name to lookup. This is a
  540.                      * pointer into the fileName buffer of
  541.                      * *redirectInfoPtr.  This means that the
  542.                      * caller has to be careful and not
  543.                      * reference *fileNamePtr after it calls
  544.                      * the domain lookup routine which will
  545.                      * overwrite *redirectInfoPtr */
  546. {
  547.     register char *prefix;
  548.  
  549.     if (redirectInfoPtr->prefixLength > 0) {
  550.     /*
  551.      * We are being told about a new prefix after the server
  552.      * hit a remote link.  The prefix is embedded in the
  553.      * beginning of the returned complete pathname.
  554.      */
  555.     prefix = (char *)malloc(redirectInfoPtr->prefixLength + 1);
  556.     (void)strncpy(prefix, redirectInfoPtr->fileName,
  557.             redirectInfoPtr->prefixLength);
  558.     prefix[redirectInfoPtr->prefixLength] = '\0';
  559.     Fsprefix_Load(prefix, RPC_BROADCAST_SERVER_ID, FSPREFIX_IMPORTED);
  560.     free((Address) prefix);
  561.     }
  562.     if (redirectInfoPtr->fileName[0] == '.' &&
  563.     redirectInfoPtr->fileName[1] == '.') {
  564.     register int i;
  565.     register int preLen;
  566.     register char *fileName;
  567.     /*
  568.      * The server ran off the top of its domain.  Compute a new name
  569.      * from the prefix for the domain and the relative name returned.
  570.      * Again, we use the redirectInfoPtr buffer to construct the new
  571.      * name so we have to be careful not to use fileName after the
  572.      * domain lookup routine returns.  At this point
  573.      * prefix = "/pre/fix"
  574.      * fileName = "../rest/of/path"
  575.      * and we need
  576.      * fileName = "/pre/rest/of/path"
  577.      */
  578.     prefix = prefixPtr->prefix;
  579.     fileName = redirectInfoPtr->fileName;
  580.     preLen = strlen(prefix);
  581.     /*
  582.      * Scan the prefix from the right end for the first '/'
  583.      */
  584.     for (i = preLen-1; i >= 0 ; i--) {
  585.         if (prefix[i] == '/') {
  586.         break;
  587.         }
  588.     }
  589.     preLen = i+1;
  590.     if (preLen == 1) {
  591.         /*
  592.          * Have to shift the name to the left, up against the beginning /
  593.          */
  594.         for (i=3; ; i++) {
  595.         fileName[i-2] = fileName[i];
  596.         if (fileName[i] == '\0') {
  597.             break;
  598.         }
  599.         }
  600.     } else {
  601.         /*
  602.          * Shift the fileName over to the right so the beginning of the
  603.          * prefix can be inserted before it.  The magic 2 refers to the
  604.          * length of ".."
  605.          */
  606.         for (i = strlen(fileName); i >= 2; i--) {
  607.         fileName[i + preLen - 2] = fileName[i];
  608.         }
  609.     }
  610.     /*
  611.      * Insert the prefix.
  612.      */
  613.     for (i = 0 ; i < preLen ; i++) {
  614.         fileName[i] = prefix[i];
  615.     }
  616.     }
  617.     if (redirectInfoPtr->fileName[0] == '/') {
  618.     /*
  619.      * Either just computed a new pathname or the server returned
  620.      * an absolute name to us.
  621.      */
  622.     *fileNamePtr = redirectInfoPtr->fileName;
  623.     return(FS_LOOKUP_REDIRECT);
  624.     } else {
  625.     printf(
  626.       "Fsprefix_LookupOperation: Bad format of returned file name \"%s\".\n",
  627.       redirectInfoPtr->fileName);
  628.     return(FAILURE);
  629.     }
  630. }
  631.  
  632. /*
  633.  *----------------------------------------------------------------------
  634.  *
  635.  * NameOp --
  636.  *
  637.  *    Return a string for a name operation.
  638.  *
  639.  * Results:
  640.  *    None.
  641.  *
  642.  * Side effects:
  643.  *    Set up the list links.
  644.  *
  645.  *----------------------------------------------------------------------
  646.  */
  647. static char *
  648. NameOp(lookupOperation)
  649.     int lookupOperation;
  650. {
  651.     switch(lookupOperation) {
  652.     case FS_DOMAIN_IMPORT:
  653.         return("import");
  654.     case FS_DOMAIN_EXPORT:
  655.         return("export");
  656.     case FS_DOMAIN_OPEN:
  657.         return("open");
  658.     case FS_DOMAIN_GET_ATTR:
  659.         return("get attr");
  660.     case FS_DOMAIN_SET_ATTR:
  661.         return("set attr");
  662.     case FS_DOMAIN_MAKE_DEVICE:
  663.         return("make device");
  664.     case FS_DOMAIN_MAKE_DIR:
  665.         return("make directory");
  666.     case FS_DOMAIN_REMOVE:
  667.         return("remove");
  668.     case FS_DOMAIN_REMOVE_DIR:
  669.         return("remove directory");
  670.     case FS_DOMAIN_RENAME:
  671.         return("rename");
  672.     case FS_DOMAIN_HARD_LINK:
  673.         return("link");
  674.     default:
  675.         return("(unknown lookup operation)");
  676.     }
  677. }
  678.  
  679. /*
  680.  *----------------------------------------------------------------------
  681.  *
  682.  * Fsprefix_Init --
  683.  *
  684.  *    Initialize the prefix table.
  685.  *
  686.  * Results:
  687.  *    None.
  688.  *
  689.  * Side effects:
  690.  *    Set up the list links.
  691.  *
  692.  *----------------------------------------------------------------------
  693.  */
  694. void
  695. Fsprefix_Init()
  696. {
  697.     List_Init(prefixList);
  698. }
  699.  
  700. /*
  701.  *----------------------------------------------------------------------
  702.  *
  703.  * Fsprefix_Install --
  704.  *
  705.  *    Add an entry to the prefix table.
  706.  *
  707.  * Results:
  708.  *    A pointer to the prefix table entry.
  709.  *
  710.  * Side effects:
  711.  *    Add an entry to the prefix table.
  712.  *
  713.  *----------------------------------------------------------------------
  714.  */
  715. ENTRY Fsprefix *
  716. Fsprefix_Install(prefix, hdrPtr, domainType, flags)
  717.     char        *prefix;    /* String to install as a prefix */
  718.     Fs_HandleHeader    *hdrPtr;    /* Handle from server of the prefix */
  719.     int            domainType;    /* Default domain type for prefix. */
  720.     int            flags;    /* FSPREFIX_EXPORTED | FSPREFIX_IMPORTED. */
  721. {
  722.     register Fsprefix *prefixPtr;
  723.  
  724.     LOCK_MONITOR;
  725.  
  726.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  727.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  728.         /*
  729.          * Update information in the table.
  730.          */
  731.         PrefixUpdate(prefixPtr, FS_NO_SERVER, hdrPtr, domainType, flags);
  732.         UNLOCK_MONITOR;
  733.         return(prefixPtr);
  734.     }
  735.     }
  736.     prefixPtr = PrefixInsert(prefix, FS_NO_SERVER, hdrPtr, domainType, flags);
  737.     UNLOCK_MONITOR;
  738.     return(prefixPtr);
  739. }
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * Fsprefix_Load --
  745.  *
  746.  *    Force a prefix to occur in the prefix table.  This is needed because
  747.  *    the Unix Domain server does not do REDIRECTS right so we have
  748.  *    no other way to forcibly load a prefix.
  749.  *
  750.  * Results:
  751.  *    None.
  752.  *
  753.  * Side effects:
  754.  *    Add an entry to the prefix table.  
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */
  758. ENTRY void
  759. Fsprefix_Load(prefix, serverID, flags)
  760.     char *prefix;        /* String to install as a prefix */
  761.     int  serverID;        /* Id of server for prefix */
  762.     int flags;            /* Prefix flags from fsPrefix.h */
  763. {
  764.     register Fsprefix *prefixPtr;
  765.  
  766.     LOCK_MONITOR;
  767.  
  768.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  769.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  770.         /*
  771.          * Update information in the table.
  772.          */
  773.         PrefixUpdate(prefixPtr, serverID, (Fs_HandleHeader *)NIL, -1, 
  774.         flags);    
  775.         UNLOCK_MONITOR;
  776.         return;
  777.     }
  778.     }
  779.     /*
  780.      * Add new entry to the table.
  781.      */
  782.     (void)PrefixInsert(prefix, serverID, (Fs_HandleHeader *)NIL, -1,
  783.             flags);
  784.     UNLOCK_MONITOR;
  785.     return;
  786. }
  787.  
  788. /*
  789.  *----------------------------------------------------------------------
  790.  *
  791.  * PrefixInsert --
  792.  *
  793.  *    Insert an entry into the prefix table. If the hdtPtr is not
  794.  *    NIL then the serverID it contains is used, otherwise the
  795.  *    serverID parameter is used.
  796.  *
  797.  * Results:
  798.  *    None.
  799.  *
  800.  * Side effects:
  801.  *    Sets the hdrPtr, etc. of the prefix.  Also resets number of
  802.  *    active opens/delay opens state for the prefix.
  803.  *
  804.  *----------------------------------------------------------------------
  805.  */
  806. static INTERNAL Fsprefix *
  807. PrefixInsert(prefix, serverID, hdrPtr, domainType, flags)
  808.     char        *prefix;    /* The prefix itself */
  809.     int            serverID;    /* Id of server for prefix */
  810.     Fs_HandleHeader    *hdrPtr;    /* Handle for the prefix from server */
  811.     int            domainType;    /* Domain type of handle */
  812.     int            flags;        /* import, export, etc. */
  813. {
  814.     register Fsprefix *prefixPtr;
  815.     register char *prefixCopy;
  816.  
  817.     prefixPtr = (Fsprefix *)malloc(sizeof(Fsprefix));
  818.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  819.     prefixPtr->serverID    = hdrPtr->fileID.serverID;
  820.     } else {
  821.     prefixPtr->serverID    = serverID;
  822.     }
  823.     prefixPtr->prefixLength    = strlen(prefix);
  824.     prefixCopy            = (char *)malloc(prefixPtr->prefixLength+1);
  825.     (void)strcpy(prefixCopy, prefix);
  826.     prefixPtr->prefix        = prefixCopy;
  827.     prefixPtr->hdrPtr        = hdrPtr;
  828.     prefixPtr->domainType    = domainType;
  829.     prefixPtr->flags        = flags;
  830.     prefixPtr->activeOpens    = 0;
  831.     prefixPtr->delayOpens    = FALSE;
  832.     List_Init(&prefixPtr->exportList);
  833.  
  834.     /*
  835.      * At this point one could think about sorting the prefix table
  836.      * in some way.  However, for now we just add new prefixes
  837.      * to the end.  The PrefixLookup look scans the whole list anyway.
  838.      * Finally, there is a silly dependency on the ordering from
  839.      * the use of a prefix table entry to block OPENS during recovery.
  840.      * The first prefix that is controlled by a particular server is
  841.      * used to synchronize OPENS and REOPENS.  If this stupid
  842.      * dependency were removed (by using a different data
  843.      * structure, please, than the prefix table (I did all this to
  844.      * myself - my thanks to whoever fixes it)) then the prefix
  845.      * table could be sorted in order of increasing prefix length
  846.      * so that the prefix table scan could halt at the first non
  847.      * matching prefix.
  848.      */
  849.     List_Insert((List_Links *)prefixPtr, LIST_ATREAR(prefixList));
  850.     return(prefixPtr);
  851. }
  852.  
  853. /*
  854.  *----------------------------------------------------------------------
  855.  *
  856.  * PrefixUpdate --
  857.  *
  858.  *    Update a prefix table entry.  This is called in several cases:
  859.  *    during lookup redirection (via Fs_PrefixLoad), when exporting
  860.  *    a local domain as part of bootstrap, and when setting up the
  861.  *    serverID for domains not reachable by broadcast.  Basically,
  862.  *    if there is no handle associated with the prefix then the
  863.  *    handle that was passed in is installed.  Otherwise, we let
  864.  *    the flags change in order to export an existing entry, and
  865.  *    we let the serverID field be set in order to by-pass broadcast.
  866.  *
  867.  * Results:
  868.  *    None.
  869.  *
  870.  * Side effects:
  871.  *    Reinitializes the hdrPtr, etc. of the prefix.  Also resets number of
  872.  *    active opens/delay opens state for the prefix.
  873.  *
  874.  *----------------------------------------------------------------------
  875.  */
  876. static INTERNAL void
  877. PrefixUpdate(prefixPtr, serverID, hdrPtr, domainType, flags)
  878.     Fsprefix        *prefixPtr;    /* Table entry to update */
  879.     int            serverID;    /* Id of server for prefix */
  880.     Fs_HandleHeader    *hdrPtr;    /* Handle for the prefix from server */
  881.     int            domainType;    /* Domain type of handle */
  882.     int            flags;        /* import, export, etc. */
  883. {
  884.     if (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL) {
  885.     /*
  886.      * No handle, we are being updated during a pathname redirection.
  887.      */
  888.     prefixPtr->hdrPtr    = hdrPtr;
  889.     prefixPtr->domainType    = domainType;
  890.     prefixPtr->delayOpens    = FALSE;
  891.     prefixPtr->activeOpens    = 0;
  892.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  893.         prefixPtr->serverID = hdrPtr->fileID.serverID;
  894.     }
  895.     if (prefixPtr->flags & FSPREFIX_REMOTE) {
  896.         /*
  897.          * Save hard-wired information about the server location.
  898.          * Can only reset that info via Fsprefix_Clear.
  899.          */
  900.         flags |= FSPREFIX_REMOTE;
  901.     } else if ((hdrPtr == (Fs_HandleHeader *)NIL) &&
  902.            (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL)) {
  903.         /*
  904.          * No handle on prefix, no input handle.  Cache the input
  905.          * serverID and we'll contact it to establish
  906.          * the prefix handle.  At this point either serverID is the
  907.          * broadcast address, or serverID has a specific value and
  908.          * the FSREMOTE_PREFIX flag is set.
  909.          */
  910.         prefixPtr->serverID = serverID;
  911.     }
  912.     prefixPtr->flags    = flags & ~FSPREFIX_OVERRIDE;
  913.     } else {
  914.     /*
  915.      * Verify the new flags for the prefix table entry.
  916.      */
  917.     if (flags & FS_EXPORTED_PREFIX) {
  918.         /*
  919.          * A local prefix is being exported.  This happens during bootstrap.
  920.          */
  921.         prefixPtr->flags    |= FS_EXPORTED_PREFIX;
  922.     }
  923.     }
  924.     return;
  925. }
  926.  
  927. /*
  928.  *----------------------------------------------------------------------
  929.  *
  930.  * Fsprefix_Lookup --
  931.  *
  932.  *    Find an entry in the prefix table.  It is the caller's responsibility
  933.  *    to broadcast to get the handle for the prefix, if necessary.
  934.  *
  935.  * Results:
  936.  *    SUCCESS means there was a prefix match.  Still, *hdrPtr and
  937.  *    *domainTypePtr may be NIL to indicate that they are not
  938.  *    instantiated.
  939.  *
  940.  * Side effects:
  941.  *    None.
  942.  *
  943.  *----------------------------------------------------------------------
  944.  */
  945. ENTRY ReturnStatus
  946. Fsprefix_Lookup(fileName, flags, clientID, hdrPtrPtr, rootIDPtr, lookupNamePtr, 
  947.         serverIDPtr, domainTypePtr, prefixPtrPtr)
  948.     register char *fileName;    /* File name to match against */
  949.     int     flags;        /* FSPREFIX_IMPORTED | FSPREFIX_EXACT and
  950.                  * one of FSPREFIX_EXPORTED|FSPREFIX_LOCAL */
  951.     int        clientID;    /* Use to check export list */
  952.     Fs_HandleHeader **hdrPtrPtr;    /* Return, the handle for the prefix.  This is
  953.                  * NOT LOCKED and has no extra references. */
  954.     Fs_FileID    *rootIDPtr;    /* Return, ID of the root of the domain */
  955.     char     **lookupNamePtr;/* Return, If FS_NO_HANDLE this is the prefix
  956.                  * itself.  If SUCCESS, this is the relative
  957.                  * name after the prefix */
  958.     int        *serverIDPtr;    /* Return, If FS_NO_HANDLE this is the id
  959.                  * of the server for the prefix */
  960.     int        *domainTypePtr;    /* Return, the domain of the prefix */
  961.     Fsprefix    **prefixPtrPtr;    /* Return, prefix used to find the file */
  962. {
  963.     register Fs_ProcessState    *fsPtr;               /* For this process, to
  964.                              * return working dir.*/
  965.     register Fsprefix         *longestPrefixPtr;  /* Longest match */
  966.     register Fsprefix        *prefixPtr;        /* Pointer to table entry */
  967.     register Fs_NameInfo        *nameInfoPtr;        /* Name info for prefix */
  968.     ReturnStatus        status = SUCCESS;   /* Return value */
  969.     Boolean            exactMatch;        /* TRUE the fileName has
  970.                              * to match the prefix in 
  971.                              * the table exactly */
  972.     Boolean            wantLink;        /* TRUE if caller wants to
  973.                              * inhibit indirection via
  974.                              * a prefix so it can lstat
  975.                              * the link file itself. */
  976.  
  977.     LOCK_MONITOR;
  978.  
  979.     longestPrefixPtr = (Fsprefix *) NIL;
  980.     exactMatch = (flags & FSPREFIX_EXACT);
  981.     wantLink = (flags & FSPREFIX_LINK_NOT_PREFIX);
  982.     flags &= ~(FSPREFIX_EXACT|FSPREFIX_LINK_NOT_PREFIX);
  983.     if (fileName[0] != '/') {
  984.     /*
  985.      * For relative names just return the handle from the current
  986.      * working directory.  Also, don't accept relative names with
  987.      * exact matches - that happens occasionally in error conditions.
  988.      */
  989.     fs_Stats.prefix.relative++;
  990.     fsPtr = (Proc_GetEffectiveProc())->fsPtr;
  991.     if (!exactMatch && fsPtr->cwdPtr != (Fs_Stream *)NIL) {
  992.         *hdrPtrPtr = fsPtr->cwdPtr->ioHandlePtr;
  993.         nameInfoPtr = fsPtr->cwdPtr->nameInfoPtr;
  994.         *rootIDPtr = nameInfoPtr->rootID;
  995.         *lookupNamePtr = fileName;
  996.         *domainTypePtr = nameInfoPtr->domainType;
  997.         *prefixPtrPtr = nameInfoPtr->prefixPtr;
  998.     } else {
  999.         status = FS_FILE_NOT_FOUND;
  1000.     }
  1001.     } else {
  1002.     fs_Stats.prefix.absolute++;
  1003.     LIST_FORALL(prefixList, (List_Links *) prefixPtr) {
  1004.         if (strncmp(prefixPtr->prefix, fileName, prefixPtr->prefixLength)
  1005.                     == 0) {
  1006.         char    lastChar;
  1007.  
  1008.         if (!(flags & prefixPtr->flags)) {
  1009.             /*
  1010.              * Only hit on imported or exported prefixes, as requested.
  1011.              */
  1012.             continue;
  1013.         }
  1014.         lastChar = fileName[prefixPtr->prefixLength];
  1015.         if (exactMatch && lastChar != '\0') {
  1016.             /*
  1017.              * Need an exact match, but there is more filename left.
  1018.              */
  1019.             continue;
  1020.         } else if (wantLink && lastChar == '\0' &&
  1021.                 prefixPtr->prefixLength != 1) {
  1022.             /*
  1023.              * The opposite of exact match.  We skip an exact match
  1024.              * if we are trying to open a remote link.  This makes
  1025.              * lstat() behave the same on all remote links, whether
  1026.              * or not there is an installed prefix for the link.
  1027.              */
  1028.             continue;
  1029.         } else if ((prefixPtr->prefixLength == 1) ||
  1030.                (lastChar == '\0') || (lastChar == '/')) {
  1031.             /*
  1032.              * The prefix is "/", or the prefix matches up through
  1033.              * a complete pathname component.  This implies that
  1034.              * /spur is not a valid prefix of /spurios.
  1035.              */
  1036.             if (longestPrefixPtr == (Fsprefix *)NIL) {
  1037.             longestPrefixPtr = prefixPtr;
  1038.             } else if (longestPrefixPtr->prefixLength <
  1039.                    prefixPtr->prefixLength) {
  1040.             longestPrefixPtr = prefixPtr;
  1041.             }
  1042.         }
  1043.         }
  1044.     }
  1045.     if (longestPrefixPtr != (Fsprefix *)NIL) {
  1046.         if ((flags & FSPREFIX_EXPORTED) && (clientID >= 0) &&
  1047.         (! List_IsEmpty(&longestPrefixPtr->exportList))) {
  1048.         /*
  1049.          * Check the export list to see if the remote client has
  1050.          * access.  An empty export list implies everyone has access.
  1051.          */
  1052.         register FsprefixExport *exportPtr;
  1053.         status = FS_NO_ACCESS;
  1054.         LIST_FORALL(&longestPrefixPtr->exportList,
  1055.                 (List_Links *)exportPtr) {
  1056.             if (exportPtr->spriteID == clientID) {
  1057.             status = SUCCESS;
  1058.             break;
  1059.             }
  1060.         }
  1061.         }
  1062.         if (status == SUCCESS) {
  1063.         *hdrPtrPtr = longestPrefixPtr->hdrPtr;
  1064.         *domainTypePtr = longestPrefixPtr->domainType;
  1065.         if (*hdrPtrPtr == (Fs_HandleHeader *)NIL) {
  1066.             /*
  1067.              * Return our caller the prefix instead of a relative name
  1068.              * so it can broadcast to get the prefix's handle.  If
  1069.              * the prefix has been installed under a specific serverID
  1070.              * then we return that so internet RPC (presumably) can
  1071.              * be used to contact the server.  Otherwise we'll
  1072.              * broadcast to locate the server.
  1073.              */
  1074.             *lookupNamePtr = longestPrefixPtr->prefix;
  1075.             if (longestPrefixPtr->flags & FSPREFIX_REMOTE) {
  1076.             *serverIDPtr = longestPrefixPtr->serverID;
  1077.             } else {
  1078.             *serverIDPtr = RPC_BROADCAST_SERVER_ID;
  1079.             }
  1080.             *prefixPtrPtr = (Fsprefix *)NIL;
  1081.             status = FS_NO_HANDLE;
  1082.         } else {
  1083.             /*
  1084.              * All set, return our caller the name after the prefix.
  1085.              * A name not starting with a slash is returned as the
  1086.              * relative name.  This is because of domains that
  1087.              * think that a name starting with a slash is absolute.
  1088.              */
  1089.             *rootIDPtr = (*hdrPtrPtr)->fileID;
  1090.             *lookupNamePtr = &fileName[longestPrefixPtr->prefixLength];
  1091.             while (**lookupNamePtr == '/') {
  1092.             (*lookupNamePtr)++;
  1093.             }
  1094.             *prefixPtrPtr = longestPrefixPtr;
  1095.         }
  1096.         }
  1097.     } else {
  1098.         status = FS_FILE_NOT_FOUND;
  1099.     }
  1100.     }
  1101.     UNLOCK_MONITOR;
  1102.     return(status);
  1103. }
  1104.  
  1105. /*
  1106.  *----------------------------------------------------------------------
  1107.  *
  1108.  * Fsprefix_Export --
  1109.  *
  1110.  *    Add (or subtract) a client from the export list associated with
  1111.  *    a prefix.
  1112.  *
  1113.  * Results:
  1114.  *    None.
  1115.  *
  1116.  * Side effects:
  1117.  *    Update the export list of the prefix.
  1118.  *
  1119.  *----------------------------------------------------------------------
  1120.  */
  1121. ENTRY void
  1122. Fsprefix_Export(prefix, clientID, delete)
  1123.     char *prefix;        /* Update this prefix'es export list */
  1124.     int clientID;        /* Host ID of client to which to export */
  1125.     Boolean delete;        /* If TRUE, remove the client */
  1126. {
  1127.     register Fsprefix *prefixPtr;
  1128.     register FsprefixExport *exportPtr;
  1129.     Boolean found = FALSE;
  1130.  
  1131.     LOCK_MONITOR;
  1132.  
  1133.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1134.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  1135.         LIST_FORALL(&prefixPtr->exportList, (List_Links *)exportPtr) {
  1136.         if (exportPtr->spriteID == clientID) {
  1137.             if (delete) {
  1138.             List_Remove((List_Links *)exportPtr);
  1139.             free((Address)exportPtr);
  1140.             }
  1141.             found = TRUE;
  1142.             break;
  1143.         }
  1144.         }
  1145.         if (!found && !delete) {
  1146.         exportPtr = mnew(FsprefixExport);
  1147.         List_InitElement((List_Links *)exportPtr);
  1148.         exportPtr->spriteID = clientID;
  1149.         List_Insert((List_Links *)exportPtr,
  1150.                 LIST_ATREAR(&prefixPtr->exportList));
  1151.         }
  1152.         break;
  1153.     }
  1154.     }
  1155.     UNLOCK_MONITOR;
  1156. }
  1157.  
  1158. /*
  1159.  *----------------------------------------------------------------------
  1160.  *
  1161.  * Fsprefix_Clear --
  1162.  *
  1163.  *    Clear a prefix table entry.  If the deleteFlag argument is set
  1164.  *    then the entry is removed altogether, otherwise just the
  1165.  *    handle is closed and then cleared.  This is called from Fs_Command
  1166.  *    and used during testing.  This won't delete the root prefix,
  1167.  *    although it will clear its handle so subsequent lookups will
  1168.  *    rebroadcast.
  1169.  *
  1170.  * Results:
  1171.  *    None.
  1172.  *
  1173.  * Side effects:
  1174.  *    Delete a prefix or just clear its handle.
  1175.  *
  1176.  *----------------------------------------------------------------------
  1177.  */
  1178. ENTRY ReturnStatus
  1179. Fsprefix_Clear(prefix, deleteFlag, forced)
  1180.     char *prefix;        /* String to install as a prefix */
  1181.     int deleteFlag;        /* If TRUE then the prefix is removed from
  1182.                  * the table.  Otherwise just the handle
  1183.                  * information is cleared. */
  1184.     Boolean forced;        /* If true, then this command is being forced
  1185.                  * from user-level.
  1186.                  */
  1187. {
  1188.     register Fsprefix *prefixPtr;
  1189.     Fsprefix *targetPrefixPtr = (Fsprefix *)NIL;
  1190.     Fs_FileID prefixID;
  1191.     Boolean okToNuke = TRUE;
  1192.     ReturnStatus status = SUCCESS;
  1193.  
  1194.  
  1195.     LOCK_MONITOR;
  1196.  
  1197.     /*
  1198.      * First pass to scan the table for the prefix and get the
  1199.      * flags and fileID associated with the prefix table entry.
  1200.      */
  1201.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1202.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  1203.         if (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL)) {
  1204.         /*
  1205.          * We export the prefix and have to be careful about
  1206.          * deleting the prefix table entry for it.  Only if
  1207.          * there is another prefix corresponding to the same
  1208.          * domain can we delete this one.  This situation occurs
  1209.          * during bootstrap where "/bootTmp" is aliased to "/"
  1210.          * but eventually we want to nuke the local "/" so
  1211.          * we can hook up to the network "/".
  1212.          */
  1213.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1214.             prefixID = prefixPtr->hdrPtr->fileID;
  1215.             okToNuke = FALSE;
  1216.         }
  1217.         }
  1218.         targetPrefixPtr = prefixPtr;
  1219.         break;
  1220.     }
  1221.     }
  1222.     /*
  1223.      * Second pass to look for an alias prefix.
  1224.      */
  1225.     if (!okToNuke) {
  1226.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1227.         if (strcmp(prefixPtr->prefix, prefix) != 0) {
  1228.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1229.             register Fs_HandleHeader *hdrPtr = prefixPtr->hdrPtr;
  1230.             if (prefixID.type != hdrPtr->fileID.type ||
  1231.             prefixID.serverID != hdrPtr->fileID.serverID ||
  1232.             prefixID.major != hdrPtr->fileID.major ||
  1233.             prefixID.minor != hdrPtr->fileID.minor) {
  1234.             continue;
  1235.             }
  1236.             /*
  1237.              * Found an alias.
  1238.              */
  1239.             goto nukeIt;
  1240.         }
  1241.         }
  1242.     }
  1243.     /*
  1244.      * No other alias
  1245.      */
  1246.     status = FAILURE;
  1247.     goto done;
  1248.     }
  1249. nukeIt:
  1250.     if (targetPrefixPtr == (Fsprefix *)NIL) {
  1251.     /*
  1252.      * No prefix match.
  1253.      */
  1254.     status = FAILURE;
  1255.     } else {
  1256.     /*
  1257.      * Was this a force-loaded prefix?  We can only delete it if this
  1258.      * command is also being forced from user level.
  1259.      */
  1260.     if ((targetPrefixPtr->flags & FSPREFIX_FORCED) && !forced) {
  1261.         status = FAILURE;
  1262.         goto done;
  1263.     }
  1264.     if (targetPrefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1265.         FsprefixHandleCloseInt(targetPrefixPtr, FSPREFIX_ANY);
  1266.     }
  1267.     targetPrefixPtr->serverID = RPC_BROADCAST_SERVER_ID;
  1268.     targetPrefixPtr->flags &= ~(FSPREFIX_EXPORTED|FSPREFIX_LOCAL);
  1269.     if (deleteFlag && targetPrefixPtr->prefixLength != 1) {
  1270.         free((Address) targetPrefixPtr->prefix);
  1271.         while (! List_IsEmpty(&targetPrefixPtr->exportList)) {
  1272.         register FsprefixExport *exportPtr;
  1273.         exportPtr =
  1274.             (FsprefixExport *)List_First(&targetPrefixPtr->exportList);
  1275.         List_Remove((List_Links *)exportPtr);
  1276.         free((Address)exportPtr);
  1277.         }
  1278.     
  1279.         List_Remove((List_Links *)targetPrefixPtr);
  1280.         free((Address) targetPrefixPtr);
  1281.     }
  1282.     status = SUCCESS;
  1283.     }
  1284. done:
  1285.     UNLOCK_MONITOR;
  1286.     return status;
  1287. }
  1288.  
  1289. /*
  1290.  *----------------------------------------------------------------------
  1291.  *
  1292.  * Fsprefix_HandleClose --
  1293.  *
  1294.  *    Close the handle associated with a prefix.  This is called when
  1295.  *    cleaning up a prefix table entry.  The flags argument indicates
  1296.  *    what sort of prefix we export to nuke, and this is used for
  1297.  *    consistency checking.
  1298.  *
  1299.  * Results:
  1300.  *    None.
  1301.  *
  1302.  * Side effects:
  1303.  *    None here, see the internal routine called inside the monitor lock.
  1304.  *
  1305.  *----------------------------------------------------------------------
  1306.  */
  1307. void
  1308. Fsprefix_HandleClose(prefixPtr, flags)
  1309.     Fsprefix *prefixPtr;
  1310.     int flags;            /* FSPREFIX_ANY, FSPREFIX_EXPORTED */
  1311. {
  1312.     LOCK_MONITOR;
  1313.     FsprefixHandleCloseInt(prefixPtr, flags);
  1314.     UNLOCK_MONITOR;
  1315. }
  1316.  
  1317. /*
  1318.  *----------------------------------------------------------------------
  1319.  *
  1320.  * FsprefixHandleCloseInt --
  1321.  *
  1322.  *    Close the handle associated with a prefix.  The serverID from
  1323.  *    the handle is saved for use in recovery later.
  1324.  *
  1325.  * Results:
  1326.  *    None.
  1327.  *
  1328.  * Side effects:
  1329.  *    Sets the prefix's hdrPtr to NIL.  This notifies the okToRecover
  1330.  *    condition if there were active opens on the prefix so that
  1331.  *    recovery can proceed on this very handle.
  1332.  *
  1333.  *----------------------------------------------------------------------
  1334.  */
  1335. void
  1336. FsprefixHandleCloseInt(prefixPtr, flags)
  1337.     Fsprefix *prefixPtr;
  1338.     int flags;
  1339. {
  1340.     register Fs_HandleHeader *hdrPtr;
  1341.     Fs_Stream dummy;
  1342.  
  1343.     if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1344.     if ((flags & FSPREFIX_IMPORTED) &&
  1345.         (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL))) {
  1346.         printf("Fsprefix_HandleClose: \"%s\" is exported (mounted)\n",
  1347.             prefixPtr->prefix);
  1348.         return;
  1349.     } else if ((flags & FSPREFIX_EXPORTED) &&
  1350.         (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL) == 0)){
  1351.         printf("Fsprefix_HandleClose: \"%s\" is not exported (mounted)\n",
  1352.             prefixPtr->prefix);
  1353.         return;
  1354.     }
  1355.     if (prefixPtr->prefix != (char *) NIL) {
  1356.         printf("Fsprefix_HandleClose deleting \"%s\"\n", prefixPtr->prefix);
  1357.     }
  1358.     hdrPtr = prefixPtr->hdrPtr;
  1359.     prefixPtr->hdrPtr = (Fs_HandleHeader *)NIL;
  1360.     Fsutil_HandleLock(hdrPtr);
  1361.     dummy.ioHandlePtr = hdrPtr;
  1362.     dummy.hdr.fileID.type = -1;
  1363.     (void)(*fsio_StreamOpTable[hdrPtr->fileID.type].close)(&dummy,
  1364.             rpc_SpriteID, 0, 0, 0, (ClientData)NIL);
  1365. #ifdef lint
  1366.     (void) Fsio_FileClose(&dummy, rpc_SpriteID, 0,
  1367.             0, 0, (ClientData)NIL);
  1368.     (void) FsrmtFileClose(&dummy, rpc_SpriteID, 0,
  1369.             0, 0, (ClientData)NIL);
  1370.     (void) Fsio_PipeClose(&dummy, rpc_SpriteID, 0,
  1371.             0, 0, (ClientData)NIL);
  1372.     (void) Fsio_DeviceClose(&dummy, rpc_SpriteID, 0,
  1373.             0, 0, (ClientData)NIL);
  1374.     (void) Fsrmt_IOClose(&dummy, rpc_SpriteID, 0,
  1375.             0, 0, (ClientData)NIL);
  1376.     (void) FspdevControlClose(&dummy, rpc_SpriteID, 0,
  1377.             0, 0, (ClientData)NIL);
  1378.     (void) FspdevPseudoStreamClose(&dummy, rpc_SpriteID, 0,
  1379.             0, 0, (ClientData)NIL);
  1380.     (void) FspdevServerStreamClose(&dummy, rpc_SpriteID, 0,
  1381.             0, 0, (ClientData)NIL);
  1382. #endif /* lint */
  1383.  
  1384.     if (prefixPtr->activeOpens > 0) {
  1385.         prefixPtr->activeOpens = 0;
  1386.         Sync_Broadcast(&prefixPtr->okToRecover);
  1387.     }
  1388.     }
  1389. }
  1390.  
  1391. /*
  1392.  *----------------------------------------------------------------------
  1393.  *
  1394.  * LocatePrefix --
  1395.  *
  1396.  *    Call a domain specific routine to get the token for a prefix.
  1397.  *
  1398.  * Results:
  1399.  *    The token for the prefix table and a return code.
  1400.  *
  1401.  * Side effects:
  1402.  *    Those of the domain specific Prefix routine.
  1403.  *
  1404.  *----------------------------------------------------------------------
  1405.  */
  1406. static ReturnStatus
  1407. LocatePrefix(fileName, serverID, domainTypePtr, hdrPtrPtr)
  1408.     char    *fileName;    /* The prefix to find the server of */
  1409.     int        serverID;    /* Id of server for prefix. */
  1410.     int        *domainTypePtr;    /* In/Out the type of the domain.  If -1 on
  1411.                  * entry then all domain prefix routines
  1412.                  * are polled in order to find the domain.
  1413.                  * Set upon return to domain type for prefix */
  1414.     Fs_HandleHeader **hdrPtrPtr;    /* The handle that the domain prefix routine
  1415.                  * returns for the prefix */
  1416. {
  1417.     register ReturnStatus    status;
  1418.     register int        domainType;
  1419.     Fs_UserIDs            ids;
  1420.  
  1421.     Fs_SetIDs(Proc_GetEffectiveProc(), &ids);
  1422.     for (domainType = 0; domainType < FS_NUM_DOMAINS; domainType++) {
  1423.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_IMPORT])
  1424.             (fileName, serverID, &ids, domainTypePtr, hdrPtrPtr);
  1425. #ifdef lint
  1426.     status = FsrmtImport(fileName, serverID, &ids, domainTypePtr,
  1427.                 hdrPtrPtr);
  1428. #endif /* lint */
  1429.     if (status == SUCCESS) {
  1430.         return(FS_NEW_PREFIX);
  1431.     } else if (status == RPC_FS_NO_PREFIX) {
  1432.         /* Delete prefix.  This won't delete it if load was also forced. */
  1433.         (void) Fsprefix_Clear(fileName, FALSE, FALSE);
  1434.     }
  1435.     }
  1436.     return(FS_FILE_NOT_FOUND);
  1437. }
  1438.  
  1439.  
  1440. /*
  1441.  *----------------------------------------------------------------------
  1442.  *
  1443.  * GetPrefix --
  1444.  *
  1445.  *    A common loop to deal with prefixes that have no handle yet.
  1446.  *    This takes care of finding the handle for a prefix if needed.
  1447.  *
  1448.  * Results:
  1449.  *    The handle for the prefix of the file.
  1450.  *
  1451.  * Side effects:
  1452.  *    May call LocatePrefix and Fsprefix_Install.
  1453.  *
  1454.  *----------------------------------------------------------------------
  1455.  */
  1456. static ReturnStatus
  1457. GetPrefix(fileName, follow, hdrPtrPtr, rootIDPtr, lookupNamePtr, domainTypePtr,
  1458.         prefixPtrPtr)
  1459.     char     *fileName;        /* File name that needs to be 
  1460.                      * operated on */
  1461.     Boolean    follow;            /* TRUE means lookup will follow links.
  1462.                      * FALSE allows opening of links */
  1463.     Fs_HandleHeader **hdrPtrPtr;        /* Result, handle for the prefix */
  1464.     Fs_FileID    *rootIDPtr;        /* Result, ID of domain root */
  1465.     char     **lookupNamePtr;    /* Result, remaining pathname to 
  1466.                      * lookup */
  1467.     int     *domainTypePtr;        /* Result, domain type of the prefix */
  1468.     Fsprefix     **prefixPtrPtr;        /* Result, reference to prefix table */
  1469. {
  1470.     ReturnStatus status;
  1471.     register int flags = FSPREFIX_IMPORTED;
  1472.     int         serverID;
  1473.  
  1474.     if (!follow) {
  1475.     flags |= FSPREFIX_LINK_NOT_PREFIX;
  1476.     }
  1477.     do {
  1478.     status = Fsprefix_Lookup(fileName, flags, FS_LOCALHOST_ID, hdrPtrPtr,
  1479.             rootIDPtr, lookupNamePtr, &serverID, domainTypePtr, 
  1480.             prefixPtrPtr);
  1481.     if (status == FS_NO_HANDLE) {
  1482.         /*
  1483.          * The prefix exists but there is not a valid file handle for it.
  1484.          * Fsprefix_Lookup has returned us the prefix in lookupName.
  1485.          */
  1486.         /*
  1487.          * If the server is ourself then return.  The prefix has 
  1488.          * probably been installed because we are going to export it
  1489.          * later and we shouldn't bother broadcasting for
  1490.          * it now.
  1491.          */
  1492.         if (serverID == rpc_SpriteID) {
  1493.         return FAILURE;
  1494.         }
  1495.         if (serverID == RPC_BROADCAST_SERVER_ID) {
  1496.         printf("Broadcasting for server of \"%s\"\n", *lookupNamePtr);
  1497.         } else {
  1498.         printf("Contacting server %d for \"%s\" prefix\n", serverID,
  1499.             *lookupNamePtr);
  1500.         }
  1501.         status = LocatePrefix(*lookupNamePtr, serverID, domainTypePtr,
  1502.                             hdrPtrPtr);
  1503.         if (status == FS_NEW_PREFIX) {
  1504.         char hostname[128];
  1505.  
  1506.         fs_Stats.prefix.found++;
  1507.  
  1508.         Net_SpriteIDToName((*hdrPtrPtr)->fileID.serverID, 128, 
  1509.             hostname);
  1510.         if (hostname[0] != '\0') {
  1511.             printf("Importing \"%s\" from %s\n", *lookupNamePtr,
  1512.                 hostname);
  1513.         } else {
  1514.             printf("Importing \"%s\" from host #%d\n", *lookupNamePtr,
  1515.             (*hdrPtrPtr)->fileID.serverID);
  1516.         }
  1517.         (void)Fsprefix_Install(*lookupNamePtr, *hdrPtrPtr,*domainTypePtr,
  1518.                 FSPREFIX_IMPORTED);
  1519.         }
  1520.     }
  1521.     } while (status == FS_NEW_PREFIX);
  1522.     return(status);
  1523. }
  1524.  
  1525. /*
  1526.  *----------------------------------------------------------------------
  1527.  *
  1528.  * Fsprefix_Reopen --
  1529.  *
  1530.  *    This is called to enter the re-open phase of recovery.
  1531.  *    This finds prefix table entries that have been
  1532.  *    cleared out (because the server went away) and tries
  1533.  *    to re-establish these - the prefix token is needed when
  1534.  *    re-opening other handles..
  1535.  *
  1536.  * Results:
  1537.  *    None.
  1538.  *
  1539.  * Side effects:
  1540.  *    Retries nil'ed prefixes.
  1541.  *
  1542.  *----------------------------------------------------------------------
  1543.  */
  1544. ENTRY void
  1545. Fsprefix_Reopen(serverID)
  1546.     int serverID;        /* Server we are recovering with */
  1547. {
  1548.     Fsprefix *prefixPtr;
  1549.     ReturnStatus status;
  1550.     Fs_HandleHeader *hdrPtr;
  1551.     int domainType;
  1552.     List_Links nilPrefixList;
  1553.  
  1554.     GetNilPrefixes(&nilPrefixList);
  1555.     while (!List_IsEmpty(&nilPrefixList)) {
  1556.     prefixPtr = (Fsprefix *)List_First(&nilPrefixList);
  1557.     if (prefixPtr->serverID == serverID ||
  1558.         prefixPtr->serverID == RPC_BROADCAST_SERVER_ID) {
  1559.         /*
  1560.          * Attempt to re-establish the prefix table entry before
  1561.          * re-opening files under that prefix.  This is needed
  1562.          * because the prefix table slot is a point of synchronization
  1563.          * between opens and re-opens.
  1564.          */
  1565.         domainType = -1;
  1566.         status = LocatePrefix(prefixPtr->prefix, prefixPtr->serverID,
  1567.                 &domainType, &hdrPtr);
  1568.         if (status == FS_NEW_PREFIX) {
  1569.         (void)Fsprefix_Install(prefixPtr->prefix, hdrPtr, domainType,
  1570.                 FSPREFIX_IMPORTED);
  1571.         }
  1572.     }
  1573.     List_Remove((List_Links *)prefixPtr);
  1574.     free(prefixPtr->prefix);
  1575.     free((Address)prefixPtr);
  1576.     }
  1577. }
  1578.  
  1579. /*
  1580.  *----------------------------------------------------------------------
  1581.  *
  1582.  * GetNilPrefixes --
  1583.  *
  1584.  *    Return a list of prefixes that have lost their handles.
  1585.  *
  1586.  * Results:
  1587.  *    None.
  1588.  *
  1589.  * Side effects:
  1590.  *    mallocs, our caller should free each element in the list.
  1591.  *
  1592.  *----------------------------------------------------------------------
  1593.  */
  1594. ENTRY static void
  1595. GetNilPrefixes(listPtr)
  1596.     List_Links *listPtr;    /* Header for list of prefix table entries */
  1597. {
  1598.     Fsprefix *prefixPtr;
  1599.  
  1600.     LOCK_MONITOR;
  1601.  
  1602.     List_Init(listPtr);
  1603.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1604.     if (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL) {
  1605.         register Fsprefix *newPrefixPtr;
  1606.  
  1607.         newPrefixPtr = mnew(Fsprefix);
  1608.         *newPrefixPtr = *prefixPtr;
  1609.         newPrefixPtr->prefix = (Address)malloc(newPrefixPtr->prefixLength + 1);
  1610.         (void)strcpy(newPrefixPtr->prefix, prefixPtr->prefix);
  1611.         List_Insert((List_Links *)newPrefixPtr, LIST_ATREAR(listPtr));
  1612.     }
  1613.     }
  1614.  
  1615.     UNLOCK_MONITOR;
  1616. }
  1617.  
  1618. /*
  1619.  *----------------------------------------------------------------------
  1620.  *
  1621.  * Fsprefix_OpenCheck --
  1622.  *
  1623.  *    This is called to indicate that an open is occurring in
  1624.  *    this domain.  This will fail if recovery is in progress
  1625.  *    with the server.
  1626.  *
  1627.  * Results:
  1628.  *    FS_DOMAIN_UNAVAILABLE if the prefix is locked up because recovery
  1629.  *    actions are in progress.
  1630.  *
  1631.  * Side effects:
  1632.  *    Blocks recovery until
  1633.  *    Fsprefix_OpenDone is called.
  1634.  *
  1635.  *----------------------------------------------------------------------
  1636.  */
  1637. ENTRY ReturnStatus
  1638. Fsprefix_OpenCheck(prefixHdrPtr)
  1639.     Fs_HandleHeader *prefixHdrPtr;    /* Handle from the prefix table */
  1640. {
  1641.     register ReturnStatus status;
  1642.     Fsprefix *prefixPtr;
  1643.     LOCK_MONITOR;
  1644.  
  1645.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1646.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1647.         (prefixPtr->hdrPtr->fileID.serverID ==
  1648.         prefixHdrPtr->fileID.serverID)) {
  1649.         if (prefixPtr->delayOpens) {
  1650.         printf( 
  1651.             "Fsprefix_OpenCheck waiting for recovery\n");
  1652.         if (Sync_Wait(&prefixPtr->okToOpen, TRUE)) {
  1653.             /*
  1654.              * Wait was interrupted by a signal.
  1655.              */
  1656.             status = FS_DOMAIN_UNAVAILABLE;
  1657.             printf("Fsprefix_OpenCheck aborted\n");
  1658.         } else {
  1659.             prefixPtr->activeOpens++;
  1660.             status = SUCCESS;
  1661.             printf("Fsprefix_OpenCheck ok\n");
  1662.         }
  1663.         } else {
  1664.         prefixPtr->activeOpens++;
  1665.         status = SUCCESS;
  1666.         }
  1667.         UNLOCK_MONITOR;
  1668.         return(status);
  1669.     }
  1670.     }
  1671.     /*
  1672.      * No match with the prefix handle.
  1673.      */
  1674.     printf( "PrefixOpenCheck: didn't find prefix");
  1675.     UNLOCK_MONITOR;
  1676.     return(FS_DOMAIN_UNAVAILABLE);
  1677. }
  1678.  
  1679. /*
  1680.  *----------------------------------------------------------------------
  1681.  *
  1682.  * Fsprefix_OpenDone --
  1683.  *
  1684.  *    The complement of FsPrefixOpenStart, this takes away the
  1685.  *    open reference count on the prefix and notifies any
  1686.  *    waiting recovery processes.
  1687.  *
  1688.  * Results:
  1689.  *    None.
  1690.  *
  1691.  * Side effects:
  1692.  *    Notifies the prefix okToRecover condition if activeOpens is zero.
  1693.  *
  1694.  *----------------------------------------------------------------------
  1695.  */
  1696. ENTRY void
  1697. Fsprefix_OpenDone(prefixHdrPtr)
  1698.     Fs_HandleHeader *prefixHdrPtr;    /* Handle from the prefix table */
  1699. {
  1700.     Fsprefix *prefixPtr;
  1701.     LOCK_MONITOR;
  1702.  
  1703.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1704.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1705.         (prefixPtr->hdrPtr->fileID.serverID ==
  1706.         prefixHdrPtr->fileID.serverID)) {
  1707.         prefixPtr->activeOpens--;
  1708.         if (prefixPtr->activeOpens < 0) {
  1709.         printf( "Fsprefix_OpenDone, neg open cnt\n");
  1710.         prefixPtr->activeOpens = 0;
  1711.         }
  1712.         if (prefixPtr->activeOpens == 0) {
  1713.         Sync_Broadcast(&prefixPtr->okToRecover);
  1714.         }
  1715.         UNLOCK_MONITOR;
  1716.         return;
  1717.     }
  1718.     }
  1719.     /*
  1720.      * No match with the prefix handle.
  1721.      */
  1722.     printf( "PrefixOpenDone: no handle match\n");
  1723.     UNLOCK_MONITOR;
  1724.     return;
  1725. }
  1726.  
  1727. /*
  1728.  *----------------------------------------------------------------------
  1729.  *
  1730.  * Fsprefix_RecoveryCheck --
  1731.  *
  1732.  *    This is called to indicate that we want to recover handles with
  1733.  *    this server.  This will block the calling process until any
  1734.  *    outstanding opens are completed so that opens and re-opens don't race.
  1735.  *
  1736.  * Results:
  1737.  *    None.
  1738.  *
  1739.  * Side effects:
  1740.  *    Blocks recovery until Fsprefix_OpenDone is called.
  1741.  *
  1742.  *----------------------------------------------------------------------
  1743.  */
  1744. ENTRY void
  1745. Fsprefix_RecoveryCheck(serverID)
  1746.     int serverID;
  1747. {
  1748.     Fsprefix *prefixPtr;
  1749.     LOCK_MONITOR;
  1750.  
  1751.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1752.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1753.         (prefixPtr->hdrPtr->fileID.serverID == serverID)) {
  1754.         while (prefixPtr->activeOpens > 0) {
  1755.         (void)Sync_Wait(&prefixPtr->okToRecover, FALSE);
  1756.         }
  1757.         prefixPtr->delayOpens = TRUE;
  1758.         UNLOCK_MONITOR;
  1759.         return;
  1760.     }
  1761.     }
  1762.     /*
  1763.      * No match with the prefix handle means the other host isn't a server.
  1764.      * There is no possibility of opens to race with re-opens.  We will
  1765.      * still need to re-open handles, however, because of remote devices.
  1766.      */
  1767.     UNLOCK_MONITOR;
  1768. }
  1769.  
  1770. /*
  1771.  *----------------------------------------------------------------------
  1772.  *
  1773.  * Fsprefix_AllowOpens --
  1774.  *
  1775.  *    As part of recovery, regular opens to a server are blocked
  1776.  *    until all the re-opens have been done.  This procedure indicates
  1777.  *    that the re-open phase is done and regular opens can proceed.
  1778.  *
  1779.  * Results:
  1780.  *    None.
  1781.  *
  1782.  * Side effects:
  1783.  *    Notifies the prefix okToOpen condition and clears the
  1784.  *    delayOpens boolean.
  1785.  *
  1786.  *----------------------------------------------------------------------
  1787.  */
  1788. ENTRY void
  1789. Fsprefix_AllowOpens(serverID)
  1790.     int serverID;        /* Server we are recovering with */
  1791. {
  1792.     Fsprefix *prefixPtr;
  1793.  
  1794.     LOCK_MONITOR;
  1795.  
  1796.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1797.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1798.         (prefixPtr->hdrPtr->fileID.serverID == serverID)) {
  1799.         prefixPtr->delayOpens = FALSE;
  1800.         Sync_Broadcast(&prefixPtr->okToOpen);
  1801.     }
  1802.     }
  1803.     UNLOCK_MONITOR;
  1804.     return;
  1805. }
  1806.  
  1807. /*
  1808.  *----------------------------------------------------------------------
  1809.  *
  1810.  * Fsprefix_FromFileID --
  1811.  *
  1812.  *    Return the prefix table entry given the fileID for the prefix.
  1813.  *    This reverse mapping is needed during recovery in order to
  1814.  *    re-establish the back pointer from a handle to the prefix
  1815.  *    table entry.  This in turn is used in ".." processing.
  1816.  *
  1817.  * Results:
  1818.  *    A pointer to the prefix table for the prefix rooted at
  1819.  *    the input fileID, or NIL if not found.
  1820.  *
  1821.  * Side effects:
  1822.  *    None.
  1823.  *
  1824.  *----------------------------------------------------------------------
  1825.  */
  1826. ENTRY Fsprefix *
  1827. Fsprefix_FromFileID(fileIDPtr)
  1828.     Fs_FileID    *fileIDPtr;        /* FileID from a client */
  1829. {
  1830.     Fsprefix *prefixPtr;
  1831.     LOCK_MONITOR;
  1832.  
  1833.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1834.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1835.         (prefixPtr->hdrPtr->fileID.serverID ==
  1836.         fileIDPtr->serverID) &&
  1837.         (prefixPtr->hdrPtr->fileID.major ==    fileIDPtr->major) &&
  1838.         (prefixPtr->hdrPtr->fileID.minor ==    fileIDPtr->minor)) {
  1839.         UNLOCK_MONITOR;
  1840.         return(prefixPtr);
  1841.     }
  1842.     }
  1843.     /*
  1844.      * No match with the fileID.
  1845.      */
  1846.     UNLOCK_MONITOR;
  1847.     return((Fsprefix *)NIL);
  1848. }
  1849.  
  1850. /*
  1851.  *----------------------------------------------------------------------
  1852.  *
  1853.  * Fsprefix_OpenInProgress --
  1854.  *
  1855.  *    This is called to find out if opens are in progress in
  1856.  *    a particular domain.  This is used by the cache consistency
  1857.  *    routines to decide if a consistency message might apply
  1858.  *    to an open hasn't quite completed.
  1859.  *
  1860.  * Results:
  1861.  *    None.
  1862.  *
  1863.  * Side effects:
  1864.  *    Blocks recovery until
  1865.  *    Fsprefix_OpenDone is called.
  1866.  *
  1867.  *----------------------------------------------------------------------
  1868.  */
  1869. ENTRY int
  1870. Fsprefix_OpenInProgress(fileIDPtr)
  1871.     Fs_FileID *fileIDPtr;        /* ID for some file */
  1872. {
  1873.     int activeOpens;
  1874.     Fsprefix *prefixPtr;
  1875.     LOCK_MONITOR;
  1876.  
  1877.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1878.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1879.         (prefixPtr->hdrPtr->fileID.serverID == fileIDPtr->serverID) &&
  1880.         (prefixPtr->hdrPtr->fileID.major ==    fileIDPtr->major)) {
  1881.         activeOpens = prefixPtr->activeOpens;
  1882.         UNLOCK_MONITOR;
  1883.         return(activeOpens);
  1884.     }
  1885.     }
  1886.     /*
  1887.      * No match with any prefix, must not be any active opens.
  1888.      */
  1889.     UNLOCK_MONITOR;
  1890.     return(0);
  1891. }
  1892.  
  1893. /*
  1894.  *----------------------------------------------------------------------
  1895.  *
  1896.  * FsPrefixInterate --
  1897.  *
  1898.  *    This is called to loop through the prefix table entries.
  1899.  *    Our caller is given 'read-only' access to the prefix table
  1900.  *    entry.  This is used for the 'df' and 'prefix' programs
  1901.  *    which call Fsprefix_Dump.
  1902.  *    
  1903.  *    Upon entry, the *prefixPtr should be NIL to indicate the
  1904.  *    beginning of the iteration.
  1905.  *
  1906.  * Results:
  1907.  *    A pointer to the next prefix table entry.
  1908.  *
  1909.  * Side effects:
  1910.  *    Marks the next prefix table entry as non-deletable, and
  1911.  *    returns a pointer to it.
  1912.  *
  1913.  *----------------------------------------------------------------------
  1914.  */
  1915. ENTRY void
  1916. FsprefixIterate(prefixPtrPtr)
  1917.     Fsprefix **prefixPtrPtr;        /* In/Out pointer to prefix entry */
  1918. {
  1919.     register Fsprefix *prefixPtr;
  1920.     LOCK_MONITOR;
  1921.  
  1922.     prefixPtr = *prefixPtrPtr;
  1923.     if (prefixPtr == (Fsprefix *)NIL) {
  1924.     prefixPtr = (Fsprefix *)List_First(prefixList);
  1925.     } else {
  1926.     prefixPtr->flags &= ~FSPREFIX_LOCKED;
  1927.     prefixPtr = (Fsprefix *)List_Next(((List_Links *)prefixPtr));
  1928.     if (List_IsAtEnd(prefixList, (List_Links *)prefixPtr)) {
  1929.         prefixPtr = (Fsprefix *)NIL;
  1930.     }
  1931.     }
  1932.     if (prefixPtr != (Fsprefix *)NIL) {
  1933.     prefixPtr->flags |= FSPREFIX_LOCKED;
  1934.     }
  1935.     *prefixPtrPtr = prefixPtr;
  1936.     UNLOCK_MONITOR;
  1937. }
  1938.  
  1939. /*
  1940.  *----------------------------------------------------------------------
  1941.  *
  1942.  * FsprefixDone --
  1943.  *
  1944.  *    This is called to terminate a prefix table iteration.  The
  1945.  *    current entry is unlocked so it could be deleted.
  1946.  *
  1947.  * Results:
  1948.  *    None.
  1949.  *
  1950.  * Side effects:
  1951.  *    Clears the FSPREFIX_LOCKED bit in the prefix table entry.
  1952.  *
  1953.  *----------------------------------------------------------------------
  1954.  */
  1955. ENTRY void
  1956. FsprefixDone(prefixPtr)
  1957.     Fsprefix *prefixPtr;
  1958. {
  1959.     LOCK_MONITOR;
  1960.  
  1961.     if (prefixPtr != (Fsprefix *)NIL) {
  1962.     prefixPtr->flags &= ~FSPREFIX_LOCKED;
  1963.     }
  1964.     UNLOCK_MONITOR;
  1965. }
  1966.  
  1967. /*
  1968.  *----------------------------------------------------------------------
  1969.  *
  1970.  * Fsprefix_Dump --
  1971.  *
  1972.  *    Dump out the prefix table to the console, or copy individual
  1973.  *    elements out to user space.
  1974.  *
  1975.  * Results:
  1976.  *    None.
  1977.  *
  1978.  * Side effects:
  1979.  *    Console prints.
  1980.  *
  1981.  *----------------------------------------------------------------------
  1982.  */
  1983.  
  1984. ReturnStatus
  1985. Fsprefix_Dump(index, argPtr)
  1986.     int index;        /* Prefix table index, -1 means dump to console */
  1987.     Address argPtr;    /* Buffer space for entry */
  1988. {
  1989.     Fsprefix *prefixPtr;        /* Pointer to table entry */
  1990.     Boolean    foundPrefix = FALSE;
  1991.     int i;
  1992.  
  1993.     i = 0;
  1994.     prefixPtr = (Fsprefix *)NIL;
  1995.     FsprefixIterate(&prefixPtr);
  1996.     while (prefixPtr != (Fsprefix *)NIL) {
  1997.     if (index < 0) {
  1998.         /*
  1999.          * Dump the prefix entry to the console.
  2000.          */
  2001.         printf("%-20s ", prefixPtr->prefix);
  2002.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  2003.         printf("(%d,%d,%d,%x) ",
  2004.                   prefixPtr->hdrPtr->fileID.serverID,
  2005.                   prefixPtr->hdrPtr->fileID.type,
  2006.                   prefixPtr->hdrPtr->fileID.major,
  2007.                   prefixPtr->hdrPtr->fileID.minor);
  2008.         } else {
  2009.         printf(" (no handle) ");
  2010.         }
  2011.         if (prefixPtr->flags & FSPREFIX_LOCAL) {
  2012.         printf(" import ");
  2013.         }
  2014.         if (prefixPtr->flags & FSPREFIX_IMPORTED) {
  2015.         printf(" import ");
  2016.         }
  2017.         if (prefixPtr->flags & FSPREFIX_EXPORTED) {
  2018.         printf(" export ");
  2019.         }
  2020.         printf("\n");
  2021.     } else if (i == index) {
  2022.         Fs_Prefix userPrefix;
  2023.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  2024.         /*
  2025.          * Call down to a domain-specific routine to get the
  2026.          * information about the domain.  We pass in a copy
  2027.          * of the file ID here because pseudo-file-system's
  2028.          * will change the ID to match the user-visible one,
  2029.          * not the internal one we use in the kernel.
  2030.          */
  2031.         Fs_FileID fileID;
  2032.         register Fs_FileID *fileIDPtr = &fileID;
  2033.  
  2034.         *fileIDPtr = prefixPtr->hdrPtr->fileID;
  2035.         (void) Fsutil_DomainInfo(fileIDPtr, &userPrefix.domainInfo);
  2036.         userPrefix.serverID    = fileIDPtr->serverID;
  2037.         userPrefix.domain    = fileIDPtr->major;
  2038.         userPrefix.fileNumber    = fileIDPtr->minor;
  2039.         userPrefix.version    = fileIDPtr->type;
  2040.         } else {
  2041.         userPrefix.serverID    = RPC_BROADCAST_SERVER_ID;
  2042.         userPrefix.domain    = -1;
  2043.         userPrefix.fileNumber    = -1;
  2044.         userPrefix.version    = -1;
  2045.         userPrefix.domainInfo.maxKbytes = -1;
  2046.         userPrefix.domainInfo.freeKbytes = -1;
  2047.         userPrefix.domainInfo.maxFileDesc = -1;
  2048.         userPrefix.domainInfo.freeFileDesc = -1;
  2049.         userPrefix.domainInfo.blockSize = -1;
  2050.         userPrefix.domainInfo.optSize = -1;
  2051.         }
  2052.         userPrefix.flags = prefixPtr->flags & ~FSPREFIX_LOCKED;
  2053.         if (prefixPtr->prefixLength >= FS_USER_PREFIX_LENGTH) {
  2054.         bcopy((Address)prefixPtr->prefix, (Address)userPrefix.prefix, FS_USER_PREFIX_LENGTH);
  2055.         userPrefix.prefix[FS_USER_PREFIX_LENGTH-1] = '\0';
  2056.         } else {
  2057.         (void)strcpy(userPrefix.prefix, prefixPtr->prefix);
  2058.         }
  2059.         Vm_CopyOut(sizeof(Fs_Prefix), (Address)&userPrefix, argPtr);
  2060.         foundPrefix = TRUE;
  2061.     }
  2062.     i++;
  2063.     if (!foundPrefix) {
  2064.         FsprefixIterate(&prefixPtr);
  2065.     } else {
  2066.         FsprefixDone(prefixPtr);
  2067.         break;
  2068.     }
  2069.     }
  2070.     if (index < 0 || foundPrefix) {
  2071.     return(SUCCESS);
  2072.     } else {
  2073.     return(FS_INVALID_ARG);
  2074.     }
  2075. }
  2076.  
  2077. /*
  2078.  *----------------------------------------------------------------------
  2079.  *
  2080.  * Fsprefix_DumpExport --
  2081.  *
  2082.  *    Return the export list of a prefix to user space.  The input
  2083.  *    buffer contains a prefix upon entry, and we then overwrite
  2084.  *    that with an array of SpriteIDs that corresponds to the export list.
  2085.  *    The end of the list is indicated by a spriteID of zero.
  2086.  *
  2087.  * Results:
  2088.  *    SUCCESS.
  2089.  *
  2090.  * Side effects:
  2091.  *    Copies stuff out to user space.
  2092.  *
  2093.  *----------------------------------------------------------------------
  2094.  */
  2095.  
  2096. ReturnStatus
  2097. Fsprefix_DumpExport(size, buffer)
  2098.     int size;        /* Size of buffer in bytes */
  2099.     Address buffer;    /* Buffer space for prefix then export list */
  2100. {
  2101.     Fsprefix *prefixPtr;    /* Pointer to table entry */
  2102.     char     prefix[FS_MAX_NAME_LENGTH];
  2103.     Fs_HandleHeader *hdrPtr;
  2104.     Fs_FileID rootID;
  2105.     char *name;
  2106.     int domain;
  2107.     int length;
  2108.     int serverID;
  2109.     ReturnStatus status;
  2110.  
  2111.     if (Fsutil_StringNCopy(FS_MAX_NAME_LENGTH, buffer, prefix, &length) !=
  2112.         SUCCESS) {
  2113.     return(SYS_ARG_NOACCESS);
  2114.     } else if (length == FS_MAX_NAME_LENGTH) {
  2115.     return(FS_INVALID_ARG);
  2116.     }
  2117.     status = Fsprefix_Lookup(prefix, FSPREFIX_EXACT|FSPREFIX_EXPORTED, -1,
  2118.         &hdrPtr, &rootID, &name, &serverID, &domain, &prefixPtr);
  2119.     if (status == SUCCESS) {
  2120.     status = DumpExportList(prefixPtr, size, buffer);
  2121.     }
  2122.     return(status);
  2123. }
  2124.  
  2125. /*
  2126.  *----------------------------------------------------------------------
  2127.  *
  2128.  * DumpExportList --
  2129.  *
  2130.  *    A monitored routine to copy out the export list to user space.
  2131.  *
  2132.  * Results:
  2133.  *    SUCCESS.
  2134.  *
  2135.  * Side effects:
  2136.  *    Copies stuff out to user space.
  2137.  *
  2138.  *----------------------------------------------------------------------
  2139.  */
  2140.  
  2141. static ReturnStatus
  2142. DumpExportList(prefixPtr, size, buffer)
  2143.     Fsprefix *prefixPtr;
  2144.     int size;
  2145.     char *buffer;
  2146. {
  2147.     int *exportList;
  2148.     int *iPtr;
  2149.     ReturnStatus status;
  2150.     FsprefixExport *exportPtr;
  2151.  
  2152.     LOCK_MONITOR;
  2153.     if (size > 1000 * sizeof(int)) {
  2154.     status = FS_INVALID_ARG;
  2155.     } else {
  2156.     exportList = (int *)malloc(size);
  2157.     bzero((Address)exportList, size);
  2158.     iPtr = exportList;
  2159.     LIST_FORALL(&prefixPtr->exportList, (List_Links *)exportPtr) {
  2160.         *iPtr = exportPtr->spriteID;
  2161.         iPtr++;
  2162.     }
  2163.     status = Vm_CopyOut(size, (Address)exportList, (Address)buffer);
  2164.     free((char *) exportList);
  2165.     }
  2166.     UNLOCK_MONITOR;
  2167.     return(status);
  2168. }
  2169.  
  2170.